{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c088c418",
   "metadata": {},
   "source": [
    "## 2. **特征构建**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "0029af84",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "# 读取 CSV 文件\n",
    "df = pd.read_csv(\"weatherHistory.csv\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf511efd",
   "metadata": {},
   "source": [
    "### 一.特征分箱\n",
    "\n",
    "在数据处理过程中，分箱是一种将连续变量划分为离散类别的方法。分箱有助于将连续数据转换为分类数据，以便于进一步分析和处理。在天气数据处理中，分箱可以帮助我们将时间、风速、风向等连续变量转换为有意义的分类，以便于后续的分析和建模"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "193c30ef",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Month</th>\n",
       "      <th>Season</th>\n",
       "      <th>Hour</th>\n",
       "      <th>TimeOfDay</th>\n",
       "      <th>Wind Speed (km/h)</th>\n",
       "      <th>WindSpeedGroup</th>\n",
       "      <th>Wind Bearing (degrees)</th>\n",
       "      <th>WindDirection</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>冬季</td>\n",
       "      <td>0</td>\n",
       "      <td>凌晨</td>\n",
       "      <td>17.1143</td>\n",
       "      <td>中</td>\n",
       "      <td>140.0</td>\n",
       "      <td>东南</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1</td>\n",
       "      <td>冬季</td>\n",
       "      <td>1</td>\n",
       "      <td>凌晨</td>\n",
       "      <td>16.6152</td>\n",
       "      <td>中</td>\n",
       "      <td>139.0</td>\n",
       "      <td>东南</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1</td>\n",
       "      <td>冬季</td>\n",
       "      <td>2</td>\n",
       "      <td>凌晨</td>\n",
       "      <td>20.2538</td>\n",
       "      <td>高</td>\n",
       "      <td>140.0</td>\n",
       "      <td>东南</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1</td>\n",
       "      <td>冬季</td>\n",
       "      <td>3</td>\n",
       "      <td>凌晨</td>\n",
       "      <td>14.4900</td>\n",
       "      <td>中</td>\n",
       "      <td>140.0</td>\n",
       "      <td>东南</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1</td>\n",
       "      <td>冬季</td>\n",
       "      <td>4</td>\n",
       "      <td>凌晨</td>\n",
       "      <td>13.9426</td>\n",
       "      <td>中</td>\n",
       "      <td>134.0</td>\n",
       "      <td>东</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Month Season  Hour TimeOfDay  Wind Speed (km/h) WindSpeedGroup  \\\n",
       "0      1     冬季     0        凌晨            17.1143              中   \n",
       "1      1     冬季     1        凌晨            16.6152              中   \n",
       "2      1     冬季     2        凌晨            20.2538              高   \n",
       "3      1     冬季     3        凌晨            14.4900              中   \n",
       "4      1     冬季     4        凌晨            13.9426              中   \n",
       "\n",
       "   Wind Bearing (degrees) WindDirection  \n",
       "0                   140.0            东南  \n",
       "1                   139.0            东南  \n",
       "2                   140.0            东南  \n",
       "3                   140.0            东南  \n",
       "4                   134.0             东  "
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将 Formatted Date 列转换为 datetime 类型\n",
    "df['Formatted Date'] = pd.to_datetime(df['Formatted Date'], utc=True)\n",
    "# 提取小时信息\n",
    "df['Hour'] = df['Formatted Date'].dt.hour\n",
    "# 对小时进行分箱处理\n",
    "hour_bins = [0, 5, 11, 17, 23]  # 分箱区间\n",
    "hour_labels = [\"凌晨\", \"早晨\", \"下午\", \"夜晚\"]  # 分箱标签\n",
    "df['TimeOfDay'] = pd.cut(df['Hour'], bins=hour_bins, labels=hour_labels, right=True, include_lowest=True)\n",
    "# 提取月份信息\n",
    "df['Month'] = df['Formatted Date'].dt.month\n",
    "# 定义季节分箱\n",
    "def get_season(month):\n",
    "    if month in [12, 1, 2]:\n",
    "        return '冬季'\n",
    "    elif month in [3, 4, 5]:\n",
    "        return '春季'\n",
    "    elif month in [6, 7, 8]:\n",
    "        return '夏季'\n",
    "    elif month in [9, 10, 11]:\n",
    "        return '秋季'\n",
    "# 应用季节分箱\n",
    "df['Season'] = df['Month'].apply(get_season)\n",
    "# 对风速进行分箱处理（假设分为：低、中、高）\n",
    "wind_speed_bins = [0, 10, 20, df['Wind Speed (km/h)'].max()]  # 分箱区间\n",
    "wind_speed_labels = [\"低\", \"中\", \"高\"]  # 分箱标签\n",
    "df['WindSpeedGroup'] = pd.cut(df['Wind Speed (km/h)'], bins=wind_speed_bins, labels=wind_speed_labels, right=False)\n",
    "# 对风向进行分箱处理（分为8个方向）\n",
    "wind_bearing_bins = [0, 45, 90, 135, 180, 225, 270, 315, 360]  # 分箱区间\n",
    "wind_bearing_labels = [\"北\", \"东北\", \"东\", \"东南\", \"南\", \"西南\", \"西\", \"西北\"]  # 分箱标签\n",
    "df['WindDirection'] = pd.cut(df['Wind Bearing (degrees)'], bins=wind_bearing_bins, labels=wind_bearing_labels, right=False, include_lowest=True)\n",
    "# 查看分箱后的结果\n",
    "df[['Month', 'Season', 'Hour', 'TimeOfDay', 'Wind Speed (km/h)', 'WindSpeedGroup', 'Wind Bearing (degrees)', 'WindDirection']].head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19cb8adb",
   "metadata": {},
   "source": [
    "### 二.归一化 \n",
    "归一化适用于数值特征，特别是当不同特征的值域差别很大时，归一化可以帮助加速收敛并提高模型性能。适合归一化的特征有：\n",
    "\n",
    "Temperature (C)（温度）\n",
    "\n",
    "Apparent Temperature (C)（体感温度）\n",
    "\n",
    "Humidity（湿度）\n",
    "\n",
    "Wind Speed (km/h)（风速）\n",
    "\n",
    "Visibility (km)（能见度）\n",
    "\n",
    "Pressure (millibars)（气压）\n",
    "\n",
    "\n",
    "下面是一个用于归一化数值特征的函数。我们使用 Min-Max 归一化 方法，将特征缩放到 [0, 1] 的范围内。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "e014f350",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Temperature (C)</th>\n",
       "      <th>Apparent Temperature (C)</th>\n",
       "      <th>Humidity</th>\n",
       "      <th>Wind Speed (km/h)</th>\n",
       "      <th>Wind Bearing (degrees)</th>\n",
       "      <th>Visibility (km)</th>\n",
       "      <th>Pressure (millibars)</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.362884</td>\n",
       "      <td>0.352912</td>\n",
       "      <td>0.89</td>\n",
       "      <td>0.268028</td>\n",
       "      <td>0.389972</td>\n",
       "      <td>0.620</td>\n",
       "      <td>0.971597</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.372334</td>\n",
       "      <td>0.365007</td>\n",
       "      <td>0.85</td>\n",
       "      <td>0.260212</td>\n",
       "      <td>0.387187</td>\n",
       "      <td>0.615</td>\n",
       "      <td>0.971110</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.380524</td>\n",
       "      <td>0.366250</td>\n",
       "      <td>0.82</td>\n",
       "      <td>0.317196</td>\n",
       "      <td>0.389972</td>\n",
       "      <td>0.615</td>\n",
       "      <td>0.970842</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.381244</td>\n",
       "      <td>0.380582</td>\n",
       "      <td>0.82</td>\n",
       "      <td>0.226929</td>\n",
       "      <td>0.389972</td>\n",
       "      <td>0.615</td>\n",
       "      <td>0.970546</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.372694</td>\n",
       "      <td>0.372380</td>\n",
       "      <td>0.86</td>\n",
       "      <td>0.218356</td>\n",
       "      <td>0.373259</td>\n",
       "      <td>0.615</td>\n",
       "      <td>0.969992</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Temperature (C)  Apparent Temperature (C)  Humidity  Wind Speed (km/h)  \\\n",
       "0         0.362884                  0.352912      0.89           0.268028   \n",
       "1         0.372334                  0.365007      0.85           0.260212   \n",
       "2         0.380524                  0.366250      0.82           0.317196   \n",
       "3         0.381244                  0.380582      0.82           0.226929   \n",
       "4         0.372694                  0.372380      0.86           0.218356   \n",
       "\n",
       "   Wind Bearing (degrees)  Visibility (km)  Pressure (millibars)  \n",
       "0                0.389972            0.620              0.971597  \n",
       "1                0.387187            0.615              0.971110  \n",
       "2                0.389972            0.615              0.970842  \n",
       "3                0.389972            0.615              0.970546  \n",
       "4                0.373259            0.615              0.969992  "
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 定义归一化函数\n",
    "def normalize(df, columns):\n",
    "    \"\"\"\n",
    "    对指定列进行 Min-Max 归一化.\n",
    "    \n",
    "    参数:\n",
    "    df: pandas DataFrame, 输入的数据框.\n",
    "    columns: list, 需要进行归一化的列名列表.\n",
    "    \n",
    "    返回:\n",
    "    pandas DataFrame, 归一化后的数据框.\n",
    "    \"\"\"\n",
    "    df_normalized = df.copy()\n",
    "    \n",
    "    for column in columns:\n",
    "        min_value = df_normalized[column].min()\n",
    "        max_value = df_normalized[column].max()\n",
    "        \n",
    "        df_normalized[column] = (df_normalized[column] - min_value) / (max_value - min_value)\n",
    "    \n",
    "    return df_normalized\n",
    "# 需要归一化的列\n",
    "columns_to_normalize = [\n",
    "    'Temperature (C)', \n",
    "    'Apparent Temperature (C)', \n",
    "    'Humidity', \n",
    "    'Wind Speed (km/h)', \n",
    "    'Wind Bearing (degrees)', \n",
    "    'Visibility (km)', \n",
    "    'Pressure (millibars)'\n",
    "]\n",
    "\n",
    "# 对指定列进行归一化\n",
    "df_normalized = normalize(df, columns_to_normalize)\n",
    "# 查看归一化后的数据\n",
    "df_normalized[columns_to_normalize].head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c06ae635",
   "metadata": {},
   "source": [
    "### 三.特征交互： \n",
    "特征交互是指通过组合现有特征来创建新的特征，以捕捉更复杂的关系。适合特征交互的特征通常是数值特征，以下特征可以进行特征交互：\n",
    "\n",
    "Temperature (C) 与 Apparent Temperature (C)：温度和体感温度的差值可以反映人体对气温的感知差异\n",
    "\n",
    "Humidity 与 Temperature (C)：湿度和温度的组合可以用来计算热指数。\n",
    "\n",
    "Wind Speed (km/h) 与 Wind Bearing (degrees)：风速和风向的组合可以用来计算风的分量（东向分量和北向分量）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "c29f9b76",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Temp_AppTemp</th>\n",
       "      <th>Temp_Humidity</th>\n",
       "      <th>AppTemp_Humidity</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.128066</td>\n",
       "      <td>0.322966</td>\n",
       "      <td>0.314092</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.135904</td>\n",
       "      <td>0.316484</td>\n",
       "      <td>0.310256</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.139367</td>\n",
       "      <td>0.312030</td>\n",
       "      <td>0.300325</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.145094</td>\n",
       "      <td>0.312620</td>\n",
       "      <td>0.312077</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.138784</td>\n",
       "      <td>0.320517</td>\n",
       "      <td>0.320247</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Temp_AppTemp  Temp_Humidity  AppTemp_Humidity\n",
       "0      0.128066       0.322966          0.314092\n",
       "1      0.135904       0.316484          0.310256\n",
       "2      0.139367       0.312030          0.300325\n",
       "3      0.145094       0.312620          0.312077\n",
       "4      0.138784       0.320517          0.320247"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 进行特征交互\n",
    "df_interaction = df_normalized.copy()\n",
    "# 新增温度和体感温度的交互特征\n",
    "df_interaction['Temp_AppTemp'] = df_interaction['Temperature (C)'] * df_interaction['Apparent Temperature (C)']\n",
    "# 新增温度和湿度的交互特征\n",
    "df_interaction['Temp_Humidity'] = df_interaction['Temperature (C)'] * df_interaction['Humidity']\n",
    "# 新增体感温度和湿度的交互特征\n",
    "df_interaction['AppTemp_Humidity'] = df_interaction['Apparent Temperature (C)'] * df_interaction['Humidity']\n",
    "# 查看特征交互后的数据\n",
    "df_interaction[['Temp_AppTemp', 'Temp_Humidity', 'AppTemp_Humidity']].head()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
